# -*- coding: utf-8 -*-

import asyncio
import os
import time

from dotenv import load_dotenv

from agent_run import agent  # noqa: E402
from agentscope_runtime.engine.app import AgentApp
from agentscope_runtime.engine.deployers.agentrun_deployer import (
    AgentRunDeployManager,
    OSSConfig,
    AgentRunConfig,
)
from agentscope_runtime.engine.schemas.agent_schemas import AgentRequest

load_dotenv(".env")

# Create AgentApp
app = AgentApp(agent=agent)


# Define endpoints
@app.endpoint("/sync")
def sync_handler(request: AgentRequest):
    return {"status": "ok", "payload": request}


@app.endpoint("/async")
async def async_handler(request: AgentRequest):
    return {"status": "ok", "payload": request}


@app.endpoint("/stream_async")
async def stream_async_handler(request: AgentRequest):
    for i in range(5):
        yield f"async chunk {i}, with request payload {request}\n"


@app.endpoint("/stream_sync")
def stream_sync_handler(request: AgentRequest):
    for i in range(5):
        yield f"sync chunk {i}, with request payload {request}\n"


@app.task("/task", queue="celery1")
def task_handler(request: AgentRequest):
    time.sleep(30)
    return {"status": "ok", "payload": request}


@app.task("/atask")
async def atask_handler(request: AgentRequest):
    await asyncio.sleep(15)
    return {"status": "ok", "payload": request}


async def deploy_app_to_agentrun():
    """Deploy AgentApp to Alibaba Cloud AgentRun"""

    # 1. Configure OSS
    oss_config = OSSConfig(
        # OSS AK/SK optional; fallback to Alibaba Cloud AK/SK
        access_key_id=os.environ.get(
            "OSS_ACCESS_KEY_ID",
            os.environ.get("ALIBABA_CLOUD_ACCESS_KEY_ID"),
        ),
        access_key_secret=os.environ.get(
            "OSS_ACCESS_KEY_SECRET",
            os.environ.get("ALIBABA_CLOUD_ACCESS_KEY_SECRET"),
        ),
    )

    # 2. Configure AgentRun
    agentrun_config = AgentRunConfig(
        access_key_id=os.environ.get("ALIBABA_CLOUD_ACCESS_KEY_ID"),
        access_key_secret=os.environ.get("ALIBABA_CLOUD_ACCESS_KEY_SECRET"),
    )

    # 3. Create AgentRunDeployManager
    deployer = AgentRunDeployManager(
        oss_config=oss_config,
        agentrun_config=agentrun_config,
        # build_root=os.path.dirname(__file__),
    )

    # 4. Deployment configuration
    deployment_config = {
        # Basic configuration
        "deploy_name": f'agent-app-example-{time.strftime("%Y%m%d%H%M%S")}',
        "telemetry_enabled": True,
        # Dependencies configuration
        "requirements": [
            "agentscope",
            "fastapi",
            "uvicorn",
        ],
        "extra_packages": [
            os.path.join(
                os.path.dirname(__file__),
                "others",
                "other_project.py",
            ),
        ],
        # Environment variables
        "environment": {
            "PYTHONPATH": "/code",
            "LOG_LEVEL": "INFO",
            "DASHSCOPE_API_KEY": os.environ.get("DASHSCOPE_API_KEY"),
        },
    }

    try:
        print("🚀 Starting AgentApp deployment to Alibaba Cloud AgentRun...")

        # 5. Execute deployment
        result = await app.deploy(
            deployer,
            **deployment_config,
        )

        print("✅ Deployment successful!")
        print(f"📍 Deployment ID: {result['deploy_id']}")
        print(f"📦 Wheel path: {result['wheel_path']}")
        print(f"🌐 OSS file URL: {result['artifact_url']}")
        print(f"🏷️ Resource name: {result['resource_name']}")
        print(f"🏢 AgentRuntime ID: {result['agentrun_id']}")

        return result, deployer

    except Exception as e:
        print(f"❌ Deployment failed: {e}")
        raise


async def deploy_from_project_directory():
    """Deploy directly from project directory (without using AgentApp)"""

    # Configuration
    oss_config = OSSConfig.from_env()
    agentrun_config = AgentRunConfig.from_env()

    deployer = AgentRunDeployManager(
        oss_config=oss_config,
        agentrun_config=agentrun_config,
    )

    # Project deployment configuration
    project_config = {
        "project_dir": os.path.dirname(
            __file__,
        ),  # Current directory as project directory
        "cmd": "python agent_run.py",  # Startup command
        "deploy_name": "agent-app-project",
        "telemetry_enabled": True,
    }

    try:
        print("🚀 Starting deployment from project directory to AgentRun...")

        result = await deployer.deploy(**project_config)

        print("✅ Project deployment successful!")
        print(f"📍 Deployment ID: {result['deploy_id']}")
        print(f"📦 Wheel path: {result['wheel_path']}")
        print(f"🌐 OSS file URL: {result['artifact_url']}")
        print(f"🏷️ Resource name: {result['resource_name']}")
        print(f"🏢 AgentRuntime ID: {result['agentrun_id']}")

        return result, deployer

    except Exception as e:
        print(f"❌ Project deployment failed: {e}")
        raise


async def deploy_from_existing_wheel():
    """Deploy from existing wheel file"""

    # Configuration
    oss_config = OSSConfig.from_env()
    agentrun_config = AgentRunConfig.from_env()

    deployer = AgentRunDeployManager(
        oss_config=oss_config,
        agentrun_config=agentrun_config,
    )

    # Assume there's an already built wheel file
    wheel_path = "/path/to/your/agent-app-1.0.0-py3-none-any.whl"

    wheel_config = {
        "external_whl_path": wheel_path,
        "deploy_name": "agent-app-from-wheel",
        "telemetry_enabled": True,
    }

    try:
        print("🚀 Starting deployment from Wheel file to AgentRun...")

        result = await deployer.deploy(**wheel_config)

        print("✅ Wheel deployment successful!")
        print(f"📍 Deployment ID: {result['deploy_id']}")
        print(f"📦 Wheel path: {result['wheel_path']}")
        print(f"🌐 OSS file URL: {result['artifact_url']}")
        print(f"🏷️ Resource name: {result['resource_name']}")
        print(f"🏢 AgentRuntime ID: {result['agentrun_id']}")

        return result, deployer

    except Exception as e:
        print(f"❌ Wheel deployment failed: {e}")
        raise


async def main():
    """Main function - demonstrates different deployment methods"""
    print("🎯 AgentRun AgentApp Deployment Example")
    print("=" * 50)

    # Check environment variables
    required_env_vars = [
        # OSS_ creds are optional; Alibaba Cloud creds are required
        "ALIBABA_CLOUD_ACCESS_KEY_ID",
        "ALIBABA_CLOUD_ACCESS_KEY_SECRET",
        "DASHSCOPE_API_KEY",
    ]

    missing_vars = [
        var for var in required_env_vars if not os.environ.get(var)
    ]
    if missing_vars:
        print(
            f"❌ Missing required environment vars: {', '.join(missing_vars)}",
        )
        print("\nPlease set the following environment variables:")
        for var in missing_vars:
            print(f"export {var}=your_value")
        return

    deployment_type = input(
        "\nChoose deployment method:\n"
        "1. Deploy using AgentApp (Recommended)\n"
        "2. Deploy directly from project directory\n"
        "3. Deploy from existing Wheel file\n"
        "Please enter your choice (1-3): ",
    ).strip()

    try:
        if deployment_type == "1":
            result, _ = await deploy_app_to_agentrun()
        elif deployment_type == "2":
            result, _ = await deploy_from_project_directory()
        elif deployment_type == "3":
            result, _ = await deploy_from_existing_wheel()
        else:
            print("❌ Invalid choice")
            return

        # Display different usage instructions based on deployment type
        if deployment_type == "1":
            print(
                f"""
        Deployment completed! Detailed information has been
        saved to the output file.

        📝 Deployment Information:
        - Deployment ID: {result['deploy_id']}
        - Resource Name: {result['resource_name']}
        - AgentRuntime ID: {result['agentrun_id']}

        🔗 Check deployment status in AgentRun console:
            {result['url']}

        📋 Next Steps:
        1. Check deployment status in AgentRun console
        2. After successful deployment, you can access your AgentApp through
           the API endpoints provided by AgentRun:

           # Health check
           curl {result['agentrun_endpoint_url']}/health

           # Test sync endpoint
           # Add "X-Agentrun-Session-Id" header to bound a fixed instance
           curl -X POST {result['agentrun_endpoint_url']}/sync \\
             -H "Content-Type: application/json" \\
             -H "X-Agentrun-Session-Id: 123" \\
             -d '{{
                  "input": [
                  {{
                    "role": "user",
                    "content": [
                      {{
                        "type": "text",
                        "text": "Hello, how are you?"
                      }}
                    ]
                  }}
                ],
                "session_id": "123"
              }}'

           # Test async endpoint
           # Add "X-Agentrun-Session-Id" header to bound a fixed instance
           curl -X POST {result['agentrun_endpoint_url']}/async \\
             -H "Content-Type: application/json" \\
             -H "X-Agentrun-Session-Id: 123" \\
             -d '{{
                  "input": [
                  {{
                    "role": "user",
                    "content": [
                      {{
                        "type": "text",
                        "text": "Hello, how are you?"
                      }}
                    ]
                  }}
                ],
                "session_id": "123"
              }}'

           # Test streaming endpoint
           # Add "X-Agentrun-Session-Id" header to bound a fixed instance
           curl -X POST {result['agentrun_endpoint_url']}/stream_async \\
             -H "Content-Type: application/json" \\
             -H "Accept: text/event-stream" \\
             -H "X-Agentrun-Session-Id: 123" \\
             --no-buffer \\
             -d '{{
                  "input": [
                  {{
                    "role": "user",
                    "content": [
                      {{
                        "type": "text",
                        "text": "Hello, how are you?"
                      }}
                    ]
                  }}
                ],
                "session_id": "123"
              }}'

        3. Configure gateway and domain name (if needed)
        """,
            )
        else:
            print(
                f"""
        Deployment completed! Detailed information has been
        saved to the output file.

        📝 Deployment Information:
        - Deployment ID: {result['deploy_id']}
        - Resource Name: {result['resource_name']}
        - AgentRuntime ID: {result['agentrun_id']}

        🔗 Check deployment status in AgentRun console: {result['url']}

        📋 Next Steps:
        1. Check deployment status in AgentRun console
        2. After successful deployment, you can access your Agent through the
           API endpoint provided by AgentRun
        3. Configure gateway and domain name (if needed)
        """,
            )

    except Exception as e:
        print(f"❌ Error occurred during execution: {e}")
        import traceback

        traceback.print_exc()


if __name__ == "__main__":
    # Run deployment
    asyncio.run(main())
